/*
 * AnimatorPanel.java
 *
 * Created on August 22, 2007, 8:10 PM
 * 
 * Copyright 2008 David D. Emory
 * 
 * This file is part of Five Points. See <http://www.fpdev.org> for
 * additional information regarding the project.
 * 
 * Five Points is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Five Points is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Five Points.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.fpdev.apps.admin.gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import org.fpdev.apps.admin.ACEvent;
import org.fpdev.apps.admin.AdminClient;
import org.fpdev.apps.admin.EventTypes;
import org.fpdev.apps.admin.gui.map.Animation;
import org.fpdev.core.transit.CalendarService;
import org.fpdev.util.FPUtil;
import org.fpdev.util.gui.GUIFactory;

/**
 *
 * @author demory
 */
public class VisualizerPanel extends JPanel implements ActionListener {

  private AdminClient ac_;
  private TimeSelector activeTime_, startTime_;
  private JTextField lengthField_,  speedField_;
  
  private List<CalendarService> servicesList_;
  private JComboBox serviceSel_;

  private JLabel startLabel_,  endLabel_;
  private JSlider progress_;
  private JButton initBtn_,  startBtn_,  pauseBtn_,  resumeBtn_, refreshBtn_, recordBtn_;
  private JCheckBox doRepeat_;

  /** Creates a new instance of AnimatorPanel */
  public VisualizerPanel(AdminClient ac) {
    super(new BorderLayout());
    this.setBorder(new EmptyBorder(10, 6, 6, 6));
    ac_ = ac;


    // DAY OF WEEK SELECTOR ROW

    servicesList_ = new ArrayList<CalendarService>();
    serviceSel_ = GUIFactory.newComboBox(80);
    for(CalendarService service : ac_.getEngine().getRoutes().getCalendarServices().getServices()) {
      serviceSel_.addItem(service.getName());
      servicesList_.add(service);
    }
    serviceSel_.addActionListener(this);

    JPanel calSvcSelRow = GUIFactory.newRowPanel();
    calSvcSelRow.add(GUIFactory.newLabel("Calendar service: "));
    calSvcSelRow.add(serviceSel_);
    calSvcSelRow.setAlignmentX(LEFT_ALIGNMENT);


    activeTime_ = new TimeSelector();
    refreshBtn_ = GUIFactory.newButton("Refresh", 100, this);

    JPanel activeTimeRow = GUIFactory.newRowPanel();
    activeTimeRow.add(Box.createHorizontalGlue());
    activeTimeRow.add(activeTime_);
    activeTimeRow.add(Box.createHorizontalStrut(5));
    activeTimeRow.add(refreshBtn_);
    activeTimeRow.add(Box.createHorizontalGlue());
    activeTimeRow.setAlignmentX(LEFT_ALIGNMENT);


    // START TIME ROW

    startTime_ = new TimeSelector();

    JPanel startTimeRow = GUIFactory.newRowPanel();
    startTimeRow.add(GUIFactory.newLabel("Start time: "));
    startTimeRow.add(startTime_);
    startTimeRow.setAlignmentX(LEFT_ALIGNMENT);


    // LENGTH ROW

    lengthField_ = GUIFactory.newTextField("60", 5, 25);

    JPanel lengthRow = new JPanel();
    lengthRow.setLayout(new BoxLayout(lengthRow, BoxLayout.X_AXIS));
    lengthRow.add(GUIFactory.newLabel("Timespan (min.): "));
    lengthRow.add(lengthField_);
    lengthRow.setAlignmentX(LEFT_ALIGNMENT);

    // SPEED ROW

    speedField_ = GUIFactory.newTextField("100", 5, 30);

    JPanel speedRow = GUIFactory.newRowPanel();
    speedRow.add(GUIFactory.newLabel("Animation Speed: "));
    speedRow.add(speedField_);
    speedRow.add(GUIFactory.newLabel("x"));
    speedRow.setAlignmentX(LEFT_ALIGNMENT);

    doRepeat_ = GUIFactory.newCheckBox("Repeat?");

    JPanel rptRow = new JPanel();
    rptRow.setLayout(new BoxLayout(rptRow, BoxLayout.X_AXIS));
    rptRow.add(doRepeat_);
    rptRow.setAlignmentX(LEFT_ALIGNMENT);

    // INITIALIZE BUTTON ROW
    /*
    initBtn_ = GUIFactory.newButton("Initialize", 100, this);

    JPanel initBtnRow = new JPanel();
    initBtnRow.setLayout(new BoxLayout(initBtnRow, BoxLayout.X_AXIS));
    initBtnRow.add(Box.createHorizontalGlue());
    initBtnRow.add(initBtn_);
    initBtnRow.add(Box.createHorizontalGlue());
    initBtnRow.setAlignmentX(LEFT_ALIGNMENT);*/


    // SLIDER LABELS ROW

    startLabel_ = GUIFactory.newLabel("S");
    endLabel_ = GUIFactory.newLabel("E");

    JPanel labelRow = GUIFactory.newRowPanel();
    labelRow.add(startLabel_);
    labelRow.add(Box.createHorizontalGlue());
    labelRow.add(endLabel_);
    labelRow.setAlignmentX(LEFT_ALIGNMENT);


    // PROGRESS SLIDER

    progress_ = new JSlider();
    progress_.setAlignmentX(LEFT_ALIGNMENT);


    // START/PAUSE/RESUME BUTTONS ROW

    startBtn_ = GUIFactory.newButton("Start", 50, this);
    pauseBtn_ = GUIFactory.newButton("Pause", 50, this);
    resumeBtn_ = GUIFactory.newButton("Resume", 50, this);
    recordBtn_ = GUIFactory.newButton("Record", 50, this);

    JPanel btnRow = GUIFactory.newRowPanel();
    btnRow.add(Box.createHorizontalGlue());
    btnRow.add(startBtn_);
    btnRow.add(Box.createHorizontalStrut(5));
    btnRow.add(pauseBtn_);
    btnRow.add(Box.createHorizontalStrut(5));
    btnRow.add(resumeBtn_);
    btnRow.add(Box.createHorizontalStrut(5));
    btnRow.add(recordBtn_);
    btnRow.add(Box.createHorizontalGlue());
    btnRow.setAlignmentX(LEFT_ALIGNMENT);

    // CONTROLS PANEL

    JPanel controlsPanel = new JPanel();
    controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.Y_AXIS));
    controlsPanel.setBorder(new CompoundBorder(new EtchedBorder(), new EmptyBorder(5, 5, 5, 5)));

    controlsPanel.add(labelRow);
    controlsPanel.add(progress_);
    controlsPanel.add(Box.createVerticalStrut(4));
    controlsPanel.add(btnRow);

    // MAIN PANEL

    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

    mainPanel.add(calSvcSelRow);
    mainPanel.add(Box.createVerticalStrut(8));

    JPanel activeTimePanel = GUIFactory.newColumnPanel();
    activeTimePanel.add(activeTimeRow);
    activeTimePanel.setBorder(new CompoundBorder(new TitledBorder("Active Time"), new EmptyBorder(5, 5, 5, 5)));

    mainPanel.add(activeTimePanel);
    mainPanel.add(Box.createVerticalStrut(8));
    
    JPanel animOptionsPanel = GUIFactory.newColumnPanel();
    animOptionsPanel.add(startTimeRow);
    animOptionsPanel.add(Box.createVerticalStrut(8));
    animOptionsPanel.add(lengthRow);
    animOptionsPanel.add(Box.createVerticalStrut(8));
    animOptionsPanel.add(speedRow);
    animOptionsPanel.add(Box.createVerticalStrut(8));
    animOptionsPanel.add(rptRow);
    animOptionsPanel.setBorder(new CompoundBorder(new TitledBorder("Animation Options"), new EmptyBorder(5, 5, 5, 5)));
    
    mainPanel.add(animOptionsPanel);
    
    //mainPanel.add(Box.createVerticalStrut(8));
    //mainPanel.add(initBtnRow);
    mainPanel.add(Box.createVerticalStrut(8));
    mainPanel.add(controlsPanel);

    this.add(mainPanel, BorderLayout.NORTH);
  }

  public void initialize() {
    ac_.getAnalysisOps().getVisualizer().setService(servicesList_.get(serviceSel_.getSelectedIndex()));
  }

  @Override
  public void actionPerformed(ActionEvent e) {

    if(e.getSource() == serviceSel_) {
      ac_.getAnalysisOps().getVisualizer().setService(servicesList_.get(serviceSel_.getSelectedIndex()));
    }

    if(e.getSource() == refreshBtn_) {
      ACEvent ave = new ACEvent(EventTypes.ANPANEL_SNAPSHOT_REFRESH);
      ave.setProperty("stime", activeTime_.getSTime());
      ac_.fireEvent(ave);
    }

    Animation anim = ac_.getAnalysisOps().getVisualizer().getAnimation();
    if (e.getSource() == startBtn_) {

      // initialize animation
      if (!FPUtil.isInteger(lengthField_.getText())) {
        ac_.msg("Length is not a valid integer");
        return;
      }
      if (!FPUtil.isInteger(speedField_.getText())) {
        ac_.msg("Speed is not a valid integer");
        return;
      }
      int startSTime = startTime_.getSTime();
      int endSTime = startSTime + 60 * (new Integer(lengthField_.getText()).intValue());
      int speed = new Integer(speedField_.getText()).intValue();
      startLabel_.setText(FPUtil.sTimeToStr(startSTime));
      endLabel_.setText(FPUtil.sTimeToStr(endSTime));
      progress_.setMinimum(startSTime);
      progress_.setMaximum(endSTime);
      progress_.setValue(startSTime);
      ac_.getAnalysisOps().getVisualizer().initAnimation(startSTime, endSTime, speed);

      // start animation
      ac_.getAnalysisOps().getVisualizer().getAnimation().start();
      ac_.getGUI().getMapPanel().setIsAnimating(true);
      return;
    }
    if(e.getSource() == recordBtn_) {
      int startSTime = startTime_.getSTime();
      int endSTime = startSTime + 60 * (new Integer(lengthField_.getText()).intValue());
      int speed = new Integer(speedField_.getText()).intValue();
      ac_.getAnalysisOps().getVisualizer().recordMovie(startSTime, endSTime, speed);
    }
    if (anim == null) {
      ac_.msg("No active animation");
      return;
    }
    if (e.getSource() == pauseBtn_) {
      anim.pause();
      ac_.getGUI().getMapPanel().setIsAnimating(false);
    }
    if (e.getSource() == resumeBtn_) {
      anim.resume();
      ac_.getGUI().getMapPanel().setIsAnimating(true);
    }


  }

  public void setProgress(int now) {
    progress_.setValue(now);
  //System.out.println("v="+now);
  }

  public boolean getDoRepeat() {
    return doRepeat_.isSelected();
  }
}
